home *** CD-ROM | disk | FTP | other *** search
- Subject: v22i006: Send multiple inputs to multiple outputs
- Newsgroups: comp.sources.unix
- Approved: rsalz@uunet.UU.NET
- X-Checksum-Snefru: 20a304ad ccfd1bd0 63a78fe0 7093dc95
-
- Submitted-by: Dan Bernstein <brnstnd@stealth.acf.nyu.edu>
- Posting-number: Volume 22, Issue 6
- Archive-name: multitee2.0
-
- [ The following one-line summary is really all you need, any other
- attempt I made to abstract the manpage ended up with the whole
- thing. :-) --r$ ]
-
- multitee - send multiple inputs to multiple outputs
-
- This program is designed for BSD 4.3 variants. Earlier systems don't
- provide true per-process non-blocking output.
-
- Files:
- CHANGES Description of changes since first distributed version
- README This document
- Makefile Installation commands
- multitee.c The program
- multitee.man Documentation
-
- Edit the options in Makefile and type make. multitee will be the
- executable program; multitee.1 will be the nroff'ed documentation.
-
- I don't pretend to know your machine's setup so there's no make install.
-
- Read CHANGES for a list of changes. Type multitee -C and multitee -W
- for copyright and warranty information, multitee -H for help.
- ---Dan
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of shell archive."
- # Contents: CHANGES README Makefile multitee.man multitee.c djberr.h
- # Wrapped by brnstnd@stealth on Tue Mar 27 11:18:08 1990
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'CHANGES' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'CHANGES'\"
- else
- echo shar: Extracting \"'CHANGES'\" \(190 characters\)
- sed "s/^X//" >'CHANGES' <<'END_OF_FILE'
- X3/27/90: multitee version 2.0
- X
- XBuffer limits so multitee won't take over the machine.
- X
- XDies correctly.
- XLots of minor improvements.
- XAll error cases dealt with.
- X
- X2/21/90: multitee version 1.0
- END_OF_FILE
- if test 190 -ne `wc -c <'CHANGES'`; then
- echo shar: \"'CHANGES'\" unpacked with wrong size!
- fi
- # end of 'CHANGES'
- fi
- if test -f 'README' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'README'\"
- else
- echo shar: Extracting \"'README'\" \(857 characters\)
- sed "s/^X//" >'README' <<'END_OF_FILE'
- Xmultitee - send multiple inputs to multiple outputs
- X
- XThis program is designed for BSD 4.3 variants. Earlier systems don't
- Xprovide true per-process non-blocking output.
- X
- Xmultitee version 2.0, March 27, 1990.
- XCopyright (c) 1990, Daniel J. Bernstein.
- XAll rights reserved.
- X
- XThis distribution packaged March 27, 1990.
- X
- XFiles:
- XCHANGES Description of changes since first distributed version
- XREADME This document
- XMakefile Installation commands
- Xmultitee.c The program
- Xmultitee.man Documentation
- X
- XEdit the options in Makefile and type make. multitee will be the
- Xexecutable program; multitee.1 will be the nroff'ed documentation.
- X
- XI don't pretend to know your machine's setup so there's no make install.
- X
- XRead CHANGES for a list of changes. Type multitee -C and multitee -W
- Xfor copyright and warranty information, multitee -H for help.
- END_OF_FILE
- if test 857 -ne `wc -c <'README'`; then
- echo shar: \"'README'\" unpacked with wrong size!
- fi
- # end of 'README'
- fi
- if test -f 'Makefile' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'Makefile'\"
- else
- echo shar: Extracting \"'Makefile'\" \(822 characters\)
- sed "s/^X//" >'Makefile' <<'END_OF_FILE'
- XCC=cc
- XCCOPTS=-O -UNOSIGINTERRUPT
- XNROFFOPTS=-man
- X
- X# -DNOSIGINTERRUPT if your machine does not have siginterrupt():
- X# such machines do not support per-process non-blocking I/O
- X# -DFDTABLESIZE=nn to override default of FD_SETSIZE
- X# -DBUFINSIZE=nnnn to override default of 4096
- X# -DMAXBUFOUTSIZE=nnnn to override the default default of 16384
- X
- Xdefault: all
- X
- Xall: multitee multitee.1
- X
- Xshar: multitee.shar
- X
- Xmultitee: multitee.o Makefile
- X $(CC) $(CCOPTS) -o multitee multitee.o
- X
- Xmultitee.o: multitee.c Makefile
- X $(CC) $(CCOPTS) -c multitee.o multitee.c
- X
- Xmultitee.1: multitee.man Makefile
- X nroff $(NROFFOPTS) < multitee.man > multitee.1
- X
- Xmultitee.shar: CHANGES README Makefile multitee.man multitee.c djberr.h
- X shar CHANGES README Makefile multitee.man multitee.c djberr.h > multitee.shar
- X chmod 400 multitee.shar
- END_OF_FILE
- if test 822 -ne `wc -c <'Makefile'`; then
- echo shar: \"'Makefile'\" unpacked with wrong size!
- fi
- # end of 'Makefile'
- fi
- if test -f 'multitee.man' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'multitee.man'\"
- else
- echo shar: Extracting \"'multitee.man'\" \(3286 characters\)
- sed "s/^X//" >'multitee.man' <<'END_OF_FILE'
- X.TH multitee 1
- X.SH NAME
- Xmultitee \- send multiple inputs to multiple outputs
- X.SH SYNTAX
- Xmultitee
- X[
- X\fB\-o\fIsz
- X] [
- X\fB\-bBv\fI
- X] [
- X\fB\-ACHUVW\fI
- X] [
- X\fIfd-fd,fd,fd...
- X] ...
- X.SH DESCRIPTION
- X.I multitee
- Xsends multiple inputs to multiple outputs.
- XGiven an argument of the form
- X.I fdin-fdout,fdout,fdout...
- Xit will send all input on file descriptor
- X.I fdin
- Xto each descriptor
- X.I fdout.
- X.I multitee
- Xwill never block reading or writing a descriptor
- X(unless it runs out of buffer space---see below).
- X.PP
- XIn the
- X.I fd
- Xarguments, hyphens can be replaced with colons,
- Xand any 0 can be omitted. Other than that, each
- X.I fd
- Xmust be an integer in the right range.
- XFuture extensions to
- X.I multitee
- Xmay abuse the syntax of these arguments,
- Xso don't insert any extra characters.
- X.PP
- XOptions
- X.B ACHUVW
- Xprint the authorship notice,
- Xcopyright notice,
- Xhelp notice,
- Xshort usage summary,
- Xversion number,
- Xand warranty information respectively.
- X.PP
- X.I multitee
- Xhas several flags:
- X.TP 12
- X\fB\-o\fIsz
- XSet maximum output buffer size to
- X.I sz,
- Xdefault 16384.
- XIf
- X.I multitee
- Xoverflows an output buffer,
- Xit will not read any more characters until the buffer
- Xempties down to the maximum buffer size.
- XThe actual maximum space taken by buffers is
- X.I sz
- Xfor each output buffer, plus 4096 per
- Xoutput
- X.I fd,
- Xthough it would take a lot of effort to
- Xachieve the latter.
- X.TP
- X\fB\-b
- XNever block, unless out of buffer space.
- XThis is the default.
- XFor example, if one output stream is blocked,
- X.I multitee
- Xwill not sit around waiting for it to clear up before it
- Xprocesses characters waiting on other streams. This helps
- Xprevent deadlock.
- X.TP
- X\fB\-B
- XDon't be so paranoid about blocking.
- XSome systems do not support true per-process non-blocking I/O;
- Xon such systems,
- X.I multitee
- Xwill refuse to run unless you specify
- X.B\-B.
- XUnder
- X.B\-B,
- X.I multitee
- Xmight block when, for instance,
- Xit writes more bytes onto a pipe than the pipe has free.
- X.PP
- X.SH "EXIT VALUE"
- X0 if all inputs reach end-of-file normally.
- X1 for usage messages.
- X2 if a file descriptor is closed.
- X3 if
- X.I multitee
- Xruns out of memory.
- X4 in various impossible situations.
- X5 if you don't specify
- X.B\-B
- Xon machines that don't support true per-process non-blocking I/O.
- X6 on an I/O error.
- X7 on an unrecognized error.
- X8 if
- X.I multitee
- Xhits a secondary storage resource limit
- X(past quota, no more disk space, past process file limit).
- X.SH DIAGNOSTICS
- X.TP
- X.I fatal: no memory
- X.I multitee
- Xhas run out of memory.
- X.TP
- X.I fatal: out of space
- X.I multitee
- Xhas exhausted a secondary storage resource,
- Xsuch as disk space, disk quota, or maximum file size.
- X.TP
- X.I fatal: nonblocking I/O not supported
- XSelf-explanatory.
- X.TP
- X.I fatal: unopened fd
- XOne of the file descriptors is not open.
- XSorry, there's no way to figure out which one.
- X.TP
- X.I fatal: I/O error
- X.I multitee
- Xhas encountered an error in disk input or output.
- X.TP
- X.I weird
- XThis includes various errors, none of which can possibly happen.
- X.SH RESTRICTIONS
- X.I multitee
- Xsimply can't work on machines without
- X.I siginterrupt(3)
- Xas well as it can on machines with that call.
- X.SH BUGS
- XNone known.
- X.SH MACHINES
- X.I multitee
- Xhas been tested
- Xon an Astronautics ZS-2 running ZSUnix
- Xand a Sun 4 running SunOS.
- X.SH VERSION
- Xmultitee version 2.0, dated March 27, 1990.
- X.SH AUTHOR
- XCopyright 1990, Daniel J. Bernstein.
- X.SH "SEE ALSO"
- Xtee(1)
- END_OF_FILE
- if test 3286 -ne `wc -c <'multitee.man'`; then
- echo shar: \"'multitee.man'\" unpacked with wrong size!
- fi
- # end of 'multitee.man'
- fi
- if test -f 'multitee.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'multitee.c'\"
- else
- echo shar: Extracting \"'multitee.c'\" \(13252 characters\)
- sed "s/^X//" >'multitee.c' <<'END_OF_FILE'
- X/*
- Xmultitee.c: send multiple inputs to multiple outputs
- X*/
- X
- Xstatic char multiteeauthor[] =
- X"multitee was written by Daniel J. Bernstein.\n\
- XInternet address: brnstnd@acf10.nyu.edu.\n";
- X
- Xstatic char multiteeversion[] =
- X"multitee version 2.0, March 27, 1990.\n\
- XCopyright (c) 1990, Daniel J. Bernstein.\n\
- XAll rights reserved.\n";
- X
- Xstatic char multiteecopyright[] =
- X"multitee version 2.0, March 27, 1990.\n\
- XCopyright (c) 1990, Daniel J. Bernstein.\n\
- XAll rights reserved.\n\
- X\n\
- XUntil January 1, 2095, you are granted the following rights: A. To make\n\
- Xcopies of this work in original form, so long as (1) the copies are exact\n\
- Xand complete; (2) the copies include the copyright notice, this paragraph,\n\
- Xand the disclaimer of warranty in their entirety. B. To distribute this\n\
- Xwork, or copies made under the provisions above, so long as (1) this is\n\
- Xthe original work and not a derivative form; (2) you do not charge a fee\n\
- Xfor copying or for distribution; (3) you ensure that the distributed form\n\
- Xincludes the copyright notice, this paragraph, and the disclaimer of\n\
- Xwarranty in their entirety. These rights are temporary and revocable upon\n\
- Xwritten, oral, or other notice by Daniel J. Bernstein. These rights are\n\
- Xautomatically revoked on January 1, 2095. This copyright notice shall be\n\
- Xgoverned by the laws of the state of New York.\n\
- X\n\
- XIf you have questions about multitee or about this copyright notice,\n\
- Xor if you would like additional rights beyond those granted above,\n\
- Xplease feel free to contact the author at brnstnd@acf10.nyu.edu\n\
- Xon the Internet.\n";
- X
- Xstatic char multiteewarranty[] =
- X"To the extent permitted by applicable law, Daniel J. Bernstein disclaims\n\
- Xall warranties, explicit or implied, including but not limited to the\n\
- Ximplied warranties of merchantability and fitness for a particular purpose.\n\
- XDaniel J. Bernstein is not and shall not be liable for any damages,\n\
- Xincidental or consequential, arising from the use of this program, even\n\
- Xif you inform him of the possibility of such damages. This disclaimer\n\
- Xshall be governed by the laws of the state of New York.\n\
- X\n\
- XIn other words, use this program at your own risk.\n\
- X\n\
- XIf you have questions about multitee or about this disclaimer of warranty,\n\
- Xplease feel free to contact the author at brnstnd@acf10.nyu.edu\n\
- Xon the Internet.\n";
- X
- Xstatic char multiteeusage[] =
- X"Usage: multitee [ -osz ] [ -bBvACHUVW ] [ fd-fd,fd,fd... ] ... \n\
- XHelp: multitee -H\n";
- X
- Xstatic char multiteehelp[] =
- X"multitee sends multiple inputs to multiple outputs.\n\
- X\n\
- Xmultitee -A: print authorship notice\n\
- Xmultitee -C: print copyright notice\n\
- Xmultitee -H: print this notice\n\
- Xmultitee -U: print short usage summary\n\
- Xmultitee -V: print version number\n\
- Xmultitee -W: print disclaimer of warranty\n\
- X\n\
- Xmultitee [ -osz ] [ -bBv ][ fd-fd,fd,fd... ] ... : read and write descriptors\n\
- X -osz: limit size of each output buffer to sz (default 16384)\n\
- X -b: never block, no matter what (default)\n\
- X -B: don't worry so much about blocking (forced on some systems)\n\
- X -v: print error messages to stderr\n\
- X fdin-fdout,fdout,fdout...: read from fdin, write to each fdout\n\
- X (0 can be left out, - can be replaced by :)\n\
- XExamples: multitee 0:1,2 like normal tee\n\
- X multitee -- -1,2 same thing (-- ends options; -1,2 is 0-1,2)\n\
- X multitee 0-6 6-1 send 0 in to 6 out while sending 6 in to 1 out\n\
- X\n\
- XIf you have questions about or suggestions for multitee, please feel free\n\
- Xto contact the author, Daniel J. Bernstein, at brnstnd@acf10.nyu.edu\n\
- Xon the Internet.\n";
- X
- X#include <stdio.h> /* just for EOF, sigh */
- X#include <sys/types.h>
- X#include <sys/time.h>
- X#include <signal.h>
- Xextern char *malloc(); /* sigh */
- X#include <errno.h>
- Xextern int errno;
- Xextern int getopt();
- Xextern char *optarg; /* these should be in getopt.h! */
- Xextern int optind;
- X#include "djberr.h"
- X
- X#define copy(dst,src,num) bcopy(src,dst,num)
- X
- X#ifndef FDTABLESIZE
- X#define FDTABLESIZE FD_SETSIZE /* or NOFILE from param.h? */
- X#endif
- X
- Xstruct fdlist
- X {
- X int fd;
- X struct fdlist *next;
- X }
- X;
- X#define FDNULL ((struct fdlist *) 0)
- X
- X#ifndef BUFINSIZE
- X#define BUFINSIZE 4096
- X#endif
- X
- X#ifndef MAXBUFOUTSIZE
- X#define MAXBUFOUTSIZE 16384
- X#endif
- X
- X/* The following kludges always work and are better than nothing. */
- X#ifndef EINVAL
- X#define EINVAL 0
- X#endif
- X#ifndef EBADF
- X#define EBADF 0
- X#endif
- X#ifndef EINTR
- X#define EINTR 0
- X#endif
- X#ifndef EWOULDBLOCK
- X#define EWOULDBLOCK 0
- X#endif
- X#ifndef EFAULT
- X#define EFAULT 0
- X#endif
- X#ifndef EIO
- X#define EIO 0
- X#endif
- X#ifndef EPIPE
- X#define EPIPE 0
- X#endif
- X#ifndef EFBIG
- X#define EFBIG 0
- X#endif
- X#ifndef ENOSPC
- X#define ENOSPC 0
- X#endif
- X#ifndef EDQUOT
- X#define EDQUOT 0
- X#endif
- X
- Xvoid nothing()
- X{
- X}
- X
- Xmain(argc,argv,envp)
- Xint argc;
- Xchar *argv[];
- Xchar *envp[];
- X{
- X int opt;
- X char *bufin;
- X int bufinsize;
- X char *oldbuf;
- X char *bufout[FDTABLESIZE];
- X int bufoutsize[FDTABLESIZE];
- X int bufoutpos[FDTABLESIZE];
- X fd_set rfds;
- X fd_set wfds;
- X int numrfds;
- X int numwfds;
- X int numfds;
- X struct fdlist *fds[FDTABLESIZE];
- X register struct fdlist *t;
- X register int i;
- X register int j;
- X register int r;
- X struct itimerval it;
- X int flagneverblock = 1;
- X int flagverbose = 0;
- X int maxbufoutsize = MAXBUFOUTSIZE;
- X int flagpastmax = 0;
- X int flagdie = 0;
- X
- X while ((opt = getopt(argc,argv,"o:bBvACHUVW")) != EOF)
- X switch(opt)
- X {
- X case 'o': maxbufoutsize = atoi(optarg); break;
- X case 'b': flagneverblock = 1; break;
- X case 'B': flagneverblock = 0; break;
- X case 'v': flagverbose = 1; break;
- X case 'A': (void) err(multiteeauthor); exit(1);
- X case 'C': (void) err(multiteecopyright); exit(1);
- X case 'H': (void) err(multiteehelp); exit(1);
- X case 'U': (void) err(multiteeusage); exit(1);
- X case 'V': (void) err(multiteeversion); exit(1);
- X case 'W': (void) err(multiteewarranty); exit(1);
- X case '?': (void) err(multiteeusage); exit(1);
- X }
- X argv += optind, argc -= optind;
- X
- X numrfds = numwfds = 0;
- X while (*argv)
- X {
- X i = 0;
- X while (**argv >= '0' && **argv <= '9')
- X i = 10 * i + *((*argv)++) - '0';
- X if (i < 0 || i >= FDTABLESIZE)
- X { if (flagverbose) err(multiteeusage); exit(1); }
- X if (**argv != '-' && **argv != ':')
- X { if (flagverbose) err(multiteeusage); exit(1); }
- X if (i + 1 > numrfds) numrfds = i + 1;
- X do
- X {
- X (*argv)++;
- X j = 0;
- X while (**argv >= '0' && **argv <= '9')
- X j = 10 * j + *((*argv)++) - '0';
- X if (j < 0 || j >= FDTABLESIZE)
- X { if (flagverbose) err(multiteeusage); exit(1); }
- X if (!(t = (struct fdlist *) malloc(sizeof(struct fdlist))))
- X /* XXXXXX: should have manually allocated avail list */
- X { if (flagverbose) errn("multitee: fatal: no memory"); exit(3); }
- X t->fd = j;
- X t->next = fds[i];
- X fds[i] = t;
- X if (j + 1 > numwfds) numwfds = j + 1;
- X }
- X while(**argv == ',');
- X if (**argv) /* not a comma but not a zero */
- X { if (flagverbose) err(multiteeusage); exit(1); }
- X argv++;
- X }
- X
- X bufinsize = BUFINSIZE;
- X if (!(bufin = malloc((unsigned) bufinsize)))
- X { if (flagverbose) errn("multitee: fatal: no memory"); exit(3); }
- X if (numrfds > numwfds)
- X numfds = numrfds;
- X else
- X numfds = numwfds;
- X if (flagneverblock)
- X {
- X#ifdef NOSIGINTERRUPT
- X if (flagverbose) errn("multitee: fatal: nonblocking I/O not supported");
- X exit(5);
- X#else
- X (void) siginterrupt(SIGALRM,1);
- X (void) signal(SIGALRM,nothing);
- X#endif
- X }
- X for (;;)
- X {
- X FD_ZERO(&rfds);
- X if (flagpastmax == 0) /* as long as somebody's past, we'll block */
- X for (i = 0;i < numrfds;i++)
- X if (fds[i] != FDNULL)
- X FD_SET(i,&rfds);
- X r = 0;
- X FD_ZERO(&wfds);
- X for (i = 0;i < numwfds;i++)
- X if (bufoutpos[i])
- X {
- X r++;
- X FD_SET(i,&wfds);
- X }
- X if (flagdie && !r)
- X exit(0); /* aaah, a normal exit */
- X r = select(numfds,&rfds,&wfds,(fd_set *) 0,(struct timeval *) 0);
- X if (r == -1)
- X switch(errno)
- X {
- X case EINTR:
- X#ifndef NOSIGINTERRUPT
- X it.it_value.tv_sec = it.it_interval.tv_sec = 0;
- X it.it_value.tv_usec = it.it_interval.tv_usec = 0;
- X (void) setitimer(ITIMER_REAL,&it,(struct itimerval *) 0);
- X#endif
- X break; /* turn ALRM off---usually unnecessary */
- X case EINVAL:
- X break; /* impossible */
- X case EBADF:
- X if (flagverbose) errn("multitee: fatal: unopened fd");
- X exit(2); /* annoying: no way to find the bad fd! */
- X default:
- X break; /* XXXXXX */
- X }
- X else if (r > 0)
- X {
- X if (flagneverblock)
- X {
- X#ifndef NOSIGINTERRUPT
- X it.it_value.tv_sec = it.it_interval.tv_sec = 0;
- X it.it_value.tv_usec = it.it_interval.tv_usec = 10000;
- X (void) setitimer(ITIMER_REAL,&it,(struct itimerval *) 0);
- X#endif
- X }
- X for (i = 0;i < numrfds;i++)
- X if (FD_ISSET(i,&rfds))
- X {
- X r = read(i,bufin,bufinsize);
- X if (r == -1)
- X switch(errno)
- X {
- X case EINTR: case EWOULDBLOCK:
- X break; /* why readable, then? */
- X case EBADF:
- X if (flagverbose) errn("multitee: weird: unopened read fd");
- X exit(4); /* impossible: select would know */
- X case EINVAL:
- X if (flagverbose) errn("multitee: weird: negative read fd");
- X exit(4); /* impossible: select would know */
- X case EFAULT:
- X if (flagverbose) errn("multitee: weird: read memory fault");
- X exit(4); /* impossible: bufin is allocated */
- X case EIO:
- X if (flagverbose) errn("multitee: fatal: read I/O error");
- X exit(6); /* XXXXXX: there's almost certainly a better way */
- X default:
- X if (flagverbose) perrn2("%s","multitee: weird: unknown error");
- X exit(7); /* if we dunno what's happening, too bad */
- X }
- X else if (r == 0) /* EOF */
- X {
- X while (fds[i] != FDNULL)
- X {
- X t = fds[i];
- X fds[i] = t->next;
- X (void) free((char *) t);
- X }
- X /* XXXXXX: should have option for ``die on eof here'' */
- X while (fds[numrfds - 1] == FDNULL)
- X numrfds--;
- X if (numrfds == 0)
- X flagdie = 1;
- X }
- X else
- X for (t = fds[i];t != FDNULL;t = t->next)
- X {
- X if (bufoutpos[t->fd] > maxbufoutsize) /* anti-aack! */
- X flagpastmax--; /* otherwise we'd count this pastmax twice */
- X if (bufoutsize[t->fd] - bufoutpos[t->fd] < r)
- X {
- X bufoutsize[t->fd] = ((bufoutpos[t->fd] + r + 255) / 256) * 256;
- X /* can't use realloc: it doesn't return sensible errors */
- X oldbuf = bufout[t->fd];
- X bufout[t->fd] = malloc((unsigned) bufoutsize[t->fd]);
- X if (bufout[t->fd])
- X {
- X (void) copy(bufout[t->fd],oldbuf,bufoutpos[t->fd]);
- X (void) free(oldbuf);
- X }
- X else
- X { /* damn, out of memory */
- X bufout[t->fd] = oldbuf;
- X /* XXXXXX: shouldn't just die... */
- X if (flagverbose) errn("multitee: fatal: no memory");
- X exit(3);
- X }
- X }
- X (void) copy(bufout[t->fd] + bufoutpos[t->fd],bufin,r);
- X bufoutpos[t->fd] += r;
- X if (bufoutpos[t->fd] > maxbufoutsize) /* aack! */
- X flagpastmax++;
- X }
- X }
- X for (i = 0;i < numwfds;i++)
- X if (FD_ISSET(i,&wfds))
- X {
- X r = write(i,bufout[i],bufoutpos[i]);
- X if (r == -1)
- X switch(errno)
- X {
- X case EINTR: case EWOULDBLOCK:
- X break; /* why writable, then? */
- X case EBADF:
- X if (flagverbose) errn("multitee: weird: unopened write fd");
- X exit(4); /* impossible: select would know */
- X case EINVAL:
- X if (flagverbose) errn("multitee: weird: negative write fd");
- X exit(4); /* impossible: select would know */
- X case EFAULT:
- X if (flagverbose) errn("multitee: weird: write memory fault");
- X exit(4); /* impossible: bufout[i] is allocated */
- X case EPIPE:
- X for (j = 0;j < numrfds;j++)
- X {
- X t = fds[j];
- X /* XXXXXX: should have option ``die on broken pipe here'' */
- X while (t != FDNULL)
- X if (t->fd == i)
- X {
- X free((char *) t);
- X t = fds[j]; /* should use extra variable, not retrace */
- X }
- X else
- X t = t->next;
- X if (fds[j] == FDNULL)
- X {
- X /* basically same as eof on read */
- X while (fds[numrfds - 1] == FDNULL)
- X numrfds--;
- X if (numrfds == 0)
- X flagdie = 1;
- X }
- X }
- X break;
- X case EFBIG: case ENOSPC: case EDQUOT:
- X if (flagverbose) errn("multitee: fatal: out of space");
- X exit(8); /* XXXXXX: what to do? this is difficult */
- X case EIO:
- X if (flagverbose) errn("multitee: fatal: write I/O error");
- X exit(6); /* XXXXXX: there's almost certainly a better way */
- X default:
- X if (flagverbose) perrn2("%s","multitee: weird: unknown error");
- X exit(7); /* if we dunno what's happening, too bad */
- X }
- X else if (r == 0)
- X {
- X ; /* wtf does this mean? */
- X }
- X else
- X {
- X if (bufoutpos[i] > maxbufoutsize) /* anti-aack! */
- X flagpastmax--;
- X bufoutpos[i] -= r;
- X if (bufoutpos[i] > 0) /* worth trading test for a function call */
- X copy(bufout[i],bufout[i] + r,bufoutpos[i]);
- X if (bufoutpos[i] > maxbufoutsize) /* aack! */
- X flagpastmax++;
- X }
- X }
- X if (flagneverblock)
- X {
- X#ifndef NOSIGINTERRUPT
- X it.it_value.tv_sec = it.it_interval.tv_sec = 0;
- X it.it_value.tv_usec = it.it_interval.tv_usec = 0;
- X (void) setitimer(ITIMER_REAL,&it,(struct itimerval *) 0);
- X#endif
- X }
- X }
- X }
- X}
- END_OF_FILE
- if test 13252 -ne `wc -c <'multitee.c'`; then
- echo shar: \"'multitee.c'\" unpacked with wrong size!
- fi
- # end of 'multitee.c'
- fi
- if test -f 'djberr.h' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'djberr.h'\"
- else
- echo shar: Extracting \"'djberr.h'\" \(491 characters\)
- sed "s/^X//" >'djberr.h' <<'END_OF_FILE'
- X/* djberr.h, 11/1/89. */
- X
- X#ifndef __DJBERRH_
- X#define __DJBERRH_
- X
- Xextern int errno;
- X
- X#define errn(s) (((void) fputs(s,stderr)), putc('\n',stderr))
- X#define err(s) (fputs(s,stderr))
- X#define errn2(s,t) (((void) fprintf(stderr,s,t)), putc('\n',stderr))
- X#define errn3(s,t,u) (((void) fprintf(stderr,s,t,u)), putc('\n',stderr))
- X#define perrn2(s,t) { int dummyerrno = errno; (void) fprintf(stderr,s,t); \
- X (void) fputs(": ",stderr); errno = dummyerrno; \
- X (void) perror(""); }
- X
- X#endif
- END_OF_FILE
- if test 491 -ne `wc -c <'djberr.h'`; then
- echo shar: \"'djberr.h'\" unpacked with wrong size!
- fi
- # end of 'djberr.h'
- fi
- echo shar: End of shell archive.
- exit 0
-
- exit 0 # Just in case...
-